package com.easychat.websocket.netty;

import com.easychat.service.impl.AsyncServiceImpl;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
ChannelDuplexHandler 是 Netty 中的一个重要组件，
它允许用户同时处理入站和出站事件。这个处理器是一个双向的 ChannelHandler，
它可以在数据流入时进行处理，同时也能在数据流出时进行操作。

ChannelDuplexHandler 的核心功能
在 Netty 的应用中，ChannelDuplexHandler 被用来接收和发送数据。
它是一个双向处理器，既可以处理入站事件（例如数据的接收），也可以处理出站事件（例如数据的发送）。
这种处理器通常用于需要同时处理入站和出站操作的场景，比如与硬件设备的通信。
 */
//@Slf4j
public class HandlerHeartBeat extends ChannelDuplexHandler {
    private static final Logger logger = LoggerFactory.getLogger(HandlerHeartBeat.class);

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        //处理超时
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                //读超时
                //通过channel的唯一id获取对应的userId，可知道是哪个用户的心跳超时了
                Channel channel = ctx.channel();
                Attribute<String> attribute = channel.attr(AttributeKey.valueOf(channel.id().toString()));
                String userId = attribute.get();
                logger.info("心跳超时，来自用户：" + userId);
                //断开连接
                ctx.close();
            } else if (event.state() == IdleState.WRITER_IDLE) {
                //写超时
                logger.info("写超时...");
                ctx.writeAndFlush("heart");
            }

        }
    }
}
